#include <iostream>
#include <vector>
#include <array>
#include <string>
#include <algorithm>
#include <numeric>
#include <span>

// 使用span处理连续内存
void process_data(std::span<int> data) {
    std::cout << "  处理 " << data.size() << " 个元素:\n  ";
    for (int& x : data) {
        x *= 2;  // 修改原始数据
        std::cout << x << " ";
    }
    std::cout << '\n';
}

// 使用固定大小的span
void process_five_elements(std::span<int, 5> data) {
    std::cout << "  处理固定5个元素:\n  ";
    for (size_t i = 0; i < data.size(); ++i) {
        data[i] = data[i] * data[i];  // 平方每个元素
        std::cout << data[i] << " ";
    }
    std::cout << '\n';
}

// 使用const span进行只读访问
int sum_data(std::span<const int> data) {
    return std::accumulate(data.begin(), data.end(), 0);
    // data[0] = 100;  // 错误：不能修改const数据
}

// 使用span进行子序列操作
void process_subspan(std::span<int> data) {
    std::cout << "  处理子序列:\n";
    
    // 前3个元素
    auto first_half = data.subspan(0, 3);
    std::cout << "  前3个: ";
    for (int x : first_half) {
        std::cout << x << " ";
    }
    std::cout << '\n';
    
    // 后3个元素
    auto last_half = data.subspan(data.size() - 3);
    std::cout << "  后3个: ";
    for (int x : last_half) {
        std::cout << x << " ";
    }
    std::cout << '\n';
    
    // 中间元素
    if (data.size() >= 3) {
        auto middle = data.subspan(1, data.size() - 2);
        std::cout << "  中间元素: ";
        for (int x : middle) {
            std::cout << x << " ";
        }
        std::cout << '\n';
    }
}

void demonstrate_span() {
    std::cout << "  C++20 跨度(span)演示:\n\n";
    
    // 1. 基本用法
    std::cout << "  基本用法:\n";
    
    // 从不同容器创建span
    int array[] = {1, 2, 3, 4, 5};
    std::span<int> span_array(array);
    
    std::vector<int> vec = {10, 20, 30, 40, 50};
    std::span<int> span_vector(vec);
    
    std::array<int, 5> arr = {100, 200, 300, 400, 500};
    std::span<int> span_std_array(arr);
    
    std::cout << "  数组span:      ";
    for (int x : span_array) {
        std::cout << x << " ";
    }
    std::cout << '\n';
    
    std::cout << "  vector span:   ";
    for (int x : span_vector) {
        std::cout << x << " ";
    }
    std::cout << '\n';
    
    std::cout << "  std::array span: ";
    for (int x : span_std_array) {
        std::cout << x << " ";
    }
    std::cout << '\n';
    
    // 2. 修改原始数据
    std::cout << "\n  通过span修改原始数据:\n";
    process_data(vec);
    
    std::cout << "  修改后的vector: ";
    for (int x : vec) {
        std::cout << x << " ";  // 应该显示每个元素都乘以2
    }
    std::cout << '\n';
    
    // 3. 固定大小的span
    std::cout << "\n  固定大小的span:\n";
    process_five_elements(arr);
    
    std::cout << "  修改后的std::array: ";
    for (int x : arr) {
        std::cout << x << " ";  // 应该显示每个元素都被平方
    }
    std::cout << '\n';
    
    // 4. const span
    std::cout << "\n  const span (只读访问):\n";
    int total = sum_data(array);
    std::cout << "  数组元素之和: " << total << '\n';
    
    // 5. 动态大小和子序列
    std::cout << "\n  动态大小和子序列:\n";
    
    std::vector<int> numbers(10);
    std::iota(numbers.begin(), numbers.end(), 1);  // 填充1到10
    
    std::cout << "  原始数据: ";
    for (int x : numbers) {
        std::cout << x << " ";
    }
    std::cout << '\n';
    
    process_subspan(numbers);
    
    // 6. 部分跨度
    std::cout << "\n  部分跨度:\n";
    
    std::array<int, 10> big_array;
    std::iota(big_array.begin(), big_array.end(), 1);  // 填充1到10
    
    // 只使用一部分数组
    std::span<int> partial_span(big_array.data() + 2, 5);  // 第3个元素开始的5个元素
    
    std::cout << "  部分span: ";
    for (int x : partial_span) {
        std::cout << x << " ";  // 应该显示3, 4, 5, 6, 7
    }
    std::cout << '\n';
    
    // 修改部分跨度
    for (int& x : partial_span) {
        x *= 10;
    }
    
    std::cout << "  修改后的完整数组: ";
    for (int x : big_array) {
        std::cout << x << " ";  // 应该显示部分元素被乘以10
    }
    std::cout << '\n';
    
    // 7. span的优势
    std::cout << "\n  span的优势:\n";
    std::cout << "  - 零开销抽象，不复制数据\n";
    std::cout << "  - 统一处理不同种类的连续容器\n";
    std::cout << "  - 支持运行时和编译期大小\n";
    std::cout << "  - 提供方便的子序列操作\n";
    std::cout << "  - 明确表示函数不会改变容器大小\n";
    
    // 8. 与之前的解决方案对比
    std::cout << "\n  与之前的解决方案对比:\n";
    std::cout << "  旧方法 (C风格): void process(int* data, size_t size);\n";
    std::cout << "  旧方法 (模板): template<typename Container> void process(Container& c);\n";
    std::cout << "  span方法: void process(std::span<int> data);\n";
} 